import Foundation
import CoreLocation

class OpenStreetMapService {
    static let shared = OpenStreetMapService()
    
    private let baseURL = "https://nominatim.openstreetmap.org"
    private let userAgent = "PhotoTour/1.0" // 建议设置用户代理
    private let timeoutInterval: TimeInterval = 30.0 // 增加超时时间
    
    private init() {}
    
    // MARK: - 正向地理编码（地址转坐标）
    func geocodeAddress(_ address: String) async -> CLLocationCoordinate2D? {
        let encodedAddress = address.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
        let urlString = "\(baseURL)/search?q=\(encodedAddress)&format=json&limit=1"
        
        guard let url = URL(string: urlString) else {
            let now = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let timestamp = formatter.string(from: now)
            print("[OpenStreetMapService.geocodeAddress] [\(timestamp)] 🗺️ [OSM] 无效URL: \(urlString)")
            return nil
        }
        
        var request = URLRequest(url: url)
        request.setValue(userAgent, forHTTPHeaderField: "User-Agent")
        request.timeoutInterval = timeoutInterval
        
        do {
            let (data, response) = try await URLSession.shared.data(for: request)
            
            guard let httpResponse = response as? HTTPURLResponse else {
                let now = Date()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                let timestamp = formatter.string(from: now)
                print("[OpenStreetMapService.geocodeAddress] [\(timestamp)] 🗺️ [OSM] 无效HTTP响应")
                return nil
            }
            
            let now = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let timestamp = formatter.string(from: now)
            print("[OpenStreetMapService.geocodeAddress] [\(timestamp)] 🗺️ [OSM] 正向地理编码响应状态: \(httpResponse.statusCode)")
            
            if httpResponse.statusCode == 200 {
                let results = try JSONDecoder().decode([OSMGeocodeResult].self, from: data)
                
                if !results.isEmpty {
                    let result = results[0]
                    let coordinate = CLLocationCoordinate2D(
                        latitude: Double(result.lat) ?? 0,
                        longitude: Double(result.lon) ?? 0
                    )
                    print("[OpenStreetMapService.geocodeAddress] [\(timestamp)] 🗺️ [OSM] 正向地理编码成功: \(address) -> \(coordinate)")
                    return coordinate
                } else {
                    print("[OpenStreetMapService.geocodeAddress] [\(timestamp)] 🗺️ [OSM] 正向地理编码失败: 无结果")
                }
            } else {
                print("[OpenStreetMapService.geocodeAddress] [\(timestamp)] 🗺️ [OSM] HTTP错误: \(httpResponse.statusCode)")
            }
        } catch {
            let now = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let timestamp = formatter.string(from: now)
            print("[OpenStreetMapService.geocodeAddress] [\(timestamp)] 🗺️ [OSM] 正向地理编码异常: \(error)")
        }
        
        return nil
    }
    
    // MARK: - 逆向地理编码（坐标转地址）
    func reverseGeocode(coordinate: CLLocationCoordinate2D) async -> GlobalLocationAddressInfo? {
        let urlString = "\(baseURL)/reverse?lat=\(coordinate.latitude)&lon=\(coordinate.longitude)&format=json&accept-language=zh-CN"
        
        guard let url = URL(string: urlString) else {
            let now = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let timestamp = formatter.string(from: now)
            print("[OpenStreetMapService.reverseGeocode] [\(timestamp)] 🗺️ [OSM] 无效URL: \(urlString)")
            return nil
        }
        
        var request = URLRequest(url: url)
        request.setValue(userAgent, forHTTPHeaderField: "User-Agent")
        request.timeoutInterval = timeoutInterval
        
        do {
            let (data, response) = try await URLSession.shared.data(for: request)
            
            guard let httpResponse = response as? HTTPURLResponse else {
                let now = Date()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                let timestamp = formatter.string(from: now)
                print("[OpenStreetMapService.reverseGeocode] [\(timestamp)] 🗺️ [OSM] 无效HTTP响应")
                return nil
            }
            
            let now = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let timestamp = formatter.string(from: now)
            print("[OpenStreetMapService.reverseGeocode] [\(timestamp)] 🗺️ [OSM] 逆向地理编码响应状态: \(httpResponse.statusCode)")
            
            if httpResponse.statusCode == 200 {
                let result = try JSONDecoder().decode(OSMReverseResult.self, from: data)
                
                let addressInfo = GlobalLocationAddressInfo(
                    country: result.address.country,
                    province: result.address.state ?? result.address.province,
                    city: result.address.city ?? result.address.town ?? result.address.village,
                    district: result.address.county ?? result.address.district,
                    township: nil,
                    street: result.address.road,
                    poiName: nil,
                    formattedAddress: result.displayName
                )
                
                print("[OpenStreetMapService.reverseGeocode] [\(timestamp)] 🗺️ [OSM] 逆向地理编码成功: \(coordinate) -> \(result.displayName)")
                return addressInfo
            } else {
                print("[OpenStreetMapService.reverseGeocode] [\(timestamp)] 🗺️ [OSM] HTTP错误: \(httpResponse.statusCode)")
            }
        } catch {
            let now = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let timestamp = formatter.string(from: now)
            print("[OpenStreetMapService.reverseGeocode] [\(timestamp)] 🗺️ [OSM] 逆向地理编码异常: \(error)")
        }
        
        return nil
    }
    
    // MARK: - 异步扩展方法
    func fetchAddressInfoAsync(coordinate: CLLocationCoordinate2D) async -> GlobalLocationAddressInfo? {
        return await reverseGeocode(coordinate: coordinate)
    }
}

// MARK: - OpenStreetMap API 响应模型
struct OSMGeocodeResult: Codable {
    let lat: String
    let lon: String
    let displayName: String
    
    enum CodingKeys: String, CodingKey {
        case lat
        case lon
        case displayName = "display_name"
    }
}

struct OSMReverseResult: Codable {
    let displayName: String
    let address: OSMAddress
    
    enum CodingKeys: String, CodingKey {
        case displayName = "display_name"
        case address
    }
}

struct OSMAddress: Codable {
    let country: String?
    let state: String?
    let province: String?
    let city: String?
    let town: String?
    let village: String?
    let county: String?
    let district: String?
    let road: String?
    let houseNumber: String?
    
    enum CodingKeys: String, CodingKey {
        case country
        case state
        case province
        case city
        case town
        case village
        case county
        case district
        case road
        case houseNumber = "house_number"
    }
} 